home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / FILES.SWG / 0070_Buffered file unit.pas < prev    next >
Pascal/Delphi Source File  |  1995-02-28  |  8KB  |  344 lines

  1. {
  2.   This is a relatively simple, fairly small, marginally tested, but extremely
  3. useful object I cooked up last week to provide a familiar interface while
  4. allowing almost a full 64K data buffer on all sorts of typed and untyped
  5. files (except for textfiles--come on, what do you think SetTextBuf is for!).
  6.  
  7.   Enjoy, and please let me know of any bugs, fixes, enhancements, ridicule,
  8. pity, thankfullness, or admiration you might have for me, thanks!
  9.  
  10. {- FastFile unit: Buffered file I/O object -}
  11.  
  12. Unit FastFile;
  13.  
  14. {
  15.      Updated 12/1/94
  16.  
  17.      Copyright 1994 by Ryan Thompson, Osiris Development.
  18.  
  19.      You are free to use this code in your programs, however,
  20.      it may not be included for-profit software, or source/unit
  21.      libraries, without my permission.
  22.  
  23.        Voice: (707)443-4803
  24.          FAX: (707)445-0599
  25.          BBS: (707)445-0500 v.32terbo/HST
  26.      FidoNet: 1:125/37.0
  27.        Email: sysop@f37.n125.z1.fidonet.org
  28.  
  29. }
  30.  
  31. INTERFACE
  32.  
  33.  
  34. Type
  35.   FileBuffer = Array[0..$fff0] of byte;
  36.  
  37.  
  38.   BufFileObj = Object
  39.     BufFile : File;
  40.     Buf : ^FileBuffer;
  41.     IOResult : Integer;
  42.     Filename : String;
  43.     Open,
  44.     Dirty : Boolean;
  45.     BufFilePos : Longint;
  46.     RecordSize,
  47.     BufSize,
  48.     BufPos,
  49.     BufTop : Word;
  50.     Constructor Init(BufferSize : Word);
  51.     Destructor Done;
  52.  
  53.     Procedure Assign(Fname : String);
  54.     Procedure Reset(RecSize : Word);
  55.     Procedure Rewrite(RecSize : Word);
  56.     Procedure Close;
  57.     Procedure Rename(Fname : String);
  58.     Procedure Erase;
  59.  
  60.     Function EOF : Boolean;
  61.     Function FilePos : Longint;
  62.     Function FileSize : Longint;
  63.     Procedure Seek(Pos : Longint);
  64.  
  65.     Procedure Read(Var V);
  66.     Procedure Write(Var V);
  67.     Procedure BlockRead(Var V; Count : Word; var Result : Word);
  68.     Procedure BlockWrite(Var V; Count : Word; var Result : Word);
  69.  
  70.     Procedure FillBuffer;
  71.     Procedure FlushBuffer;
  72.   End;
  73.   BufferedFile = ^BufFileObj;
  74.  
  75.  
  76. IMPLEMENTATION
  77.  
  78.  
  79. Constructor BufFileObj.Init(BufferSize : Word);
  80.   Begin
  81.     Filename:= '';
  82.     Open:= false;
  83.     Dirty:= false;
  84.     BufFilePos:= 0;
  85.     RecordSize:= 0;
  86.     BufSize:= BufferSize;
  87.     BufPos:= 0;
  88.     BufTop:= 0;
  89.     Getmem(Buf, BufSize);
  90.     if Buf = nil then Fail;
  91.   End;
  92.  
  93.  
  94. Destructor BufFileObj.Done;
  95.   Begin
  96.     If Open then Close;
  97.     if Buf <> nil then Freemem(Buf, BufSize);
  98.   End;
  99.  
  100.  
  101. Procedure BufFileObj.Assign(Fname : String);
  102.   Begin
  103.     if Open then Close;
  104.     Filename:= FName;
  105.     system.Assign(BufFile, Fname);
  106.     IOResult:= system.IOResult;
  107.   End;
  108.  
  109.  
  110. Procedure BufFileObj.Reset(RecSize : Word);
  111.   Begin
  112.     if Open then Close;
  113.     if RecSize = 0
  114.     then RecordSize:= 128
  115.     else RecordSize:= RecSize;
  116.     system.Reset(BufFile, 1);
  117.     IOResult:= system.IOResult;
  118.     BufFilePos:= 0;
  119.     BufPos:= 0;
  120.     FillBuffer;
  121.     if IOResult = 0
  122.     then Open:= true
  123.     else Open:= false;
  124.   End;
  125.  
  126.  
  127. Procedure BufFileObj.Rewrite(RecSize : Word);
  128.   Begin
  129.     if Open then Close;
  130.     if RecSize = 0
  131.     then RecordSize:= 128
  132.     else RecordSize:= RecSize;
  133.     BufTop:= 0;
  134.     system.Rewrite(BufFile, 1);
  135.     IOResult:= system.IOResult;
  136.     if IOResult = 0
  137.     then Open:= true
  138.     else Open:= false;
  139.   End;
  140.  
  141.  
  142. Procedure BufFileObj.Close;
  143.   Begin
  144.     If Dirty then FlushBuffer;
  145.     system.Close(BufFile);
  146.     IOResult:= system.IoResult;
  147.     Open:= false;
  148.   End;
  149.  
  150.  
  151. Procedure BufFileObj.Rename(Fname : String);
  152.   Begin
  153.     system.Rename(BufFile, Fname);
  154.     IOResult:= system.IOResult;
  155.     if IOResult = 0 then Filename:= FName;
  156.   End;
  157.  
  158.  
  159. Procedure BufFileObj.Erase;
  160.   Begin
  161.     if Open then Close;
  162.     system.Erase(BufFile);
  163.     IOResult:= system.IOResult;
  164.   End;
  165.  
  166.  
  167. Function BufFileObj.EOF : Boolean;
  168.   Begin
  169.     EOF:= BufFileObj.FilePos >= BufFileObj.FileSize;
  170.   End;
  171.  
  172.  
  173. Function BufFileObj.FileSize : Longint;
  174.   Begin
  175.     FileSize:= system.FileSize(BufFile) div RecordSize;
  176.   End;
  177.  
  178.  
  179. Function BufFileObj.FilePos : Longint;
  180.   Begin
  181.     FilePos:= (BufFilePos + BufPos) div RecordSize;
  182.   End;
  183.  
  184.  
  185. Procedure BufFileObj.Seek(Pos : Longint);
  186.   Begin
  187.     Pos:= Pos * RecordSize;
  188.     if (Pos >= BufFilePos + BufSize) or
  189.        (Pos < BufFilePos)
  190.     then begin
  191.       if Dirty then FlushBuffer;
  192.       system.seek(BufFile, Pos);
  193.       BufFilePos:= Pos;
  194.       BufPos:= 0;
  195.       FillBuffer;
  196.     end
  197.     else BufPos:= Pos - BufFilePos;
  198.     IoResult:= system.IoResult;
  199.   End;
  200.  
  201.  
  202. Procedure BufFileObj.Read(Var V);
  203.   Var
  204.     Overflow : Word;
  205.   Begin
  206.     If BufPos + RecordSize > BufTop
  207.     then begin
  208.       Overflow:= BufSize - BufPos;
  209.       Move(Buf^[BufPos], V, Overflow);
  210.       inc(BufFilePos, BufSize);
  211.       BufPos:= 0;
  212.       FillBuffer;
  213.       Move(Buf^[BufPos], FileBuffer(V)[Overflow], RecordSize - Overflow);
  214.       BufPos:= BufPos + RecordSize - Overflow;
  215.     end
  216.     else begin
  217.       Move(Buf^[BufPos], V, RecordSize);
  218.       inc(BufPos, RecordSize);
  219.     end;
  220.     IoResult:= system.IoResult;
  221.   End;
  222.  
  223.  
  224. Procedure BufFileObj.BlockRead(Var V; Count : Word; var Result : Word);
  225.   Begin
  226.     Result:= 0;
  227.     While (Result < Count) and
  228.           (IoResult = 0) and
  229.           not EOF
  230.     do begin
  231.       Read(FileBuffer(V)[Result * RecordSize]);
  232.       Inc(Result);
  233.     end;
  234.   End;
  235.  
  236.  
  237. Procedure BufFileObj.Write(Var V);
  238.   Var
  239.     Overflow : Word;
  240.   Begin
  241.     Dirty:= true;
  242.     If BufPos + RecordSize > BufSize
  243.     then begin
  244.       Overflow:= BufSize - BufPos;
  245.       if Overflow > 0
  246.       then Move(V, Buf^[BufPos], Overflow);
  247.       BufTop:= BufSize;
  248.       FlushBuffer;
  249.       inc(BufFilePos, BufSize);
  250.       BufPos:= 0;
  251.       FillBuffer;
  252.       Move(FileBuffer(V)[Overflow], Buf^[BufPos], RecordSize - Overflow);
  253.       BufPos:= BufPos + RecordSize - Overflow;
  254.     end
  255.     else begin
  256.       Move(V, Buf^[BufPos], RecordSize);
  257.       inc(BufPos, RecordSize);
  258.     end;
  259.     if BufTop < BufPos
  260.     then BufTop:= BufPos;
  261.     IoResult:= system.IoResult;
  262.   End;
  263.  
  264.  
  265. Procedure BufFileObj.BlockWrite(Var V; Count : Word; var Result : Word);
  266.   Begin
  267.     Result:= 0;
  268.     While (Result < Count) and
  269.           (IoResult = 0)
  270.     do begin
  271.       Write(FileBuffer(V)[Result * RecordSize]);
  272.       Inc(Result);
  273.     end;
  274.   End;
  275.  
  276.  
  277. Procedure BufFileObj.FillBuffer;
  278.   Begin
  279.     system.Seek(BufFile, BufFilePos);
  280.     system.BlockRead(BufFile, Buf^, BufSize, BufTop);
  281.     IoResult:= system.IoResult;
  282.     if IoResult = 0 then Dirty:= false;
  283.   End;
  284.  
  285.  
  286. Procedure BufFileObj.FlushBuffer;
  287.   Begin
  288.     system.Seek(BufFile, BufFilePos);
  289.     system.BlockWrite(BufFile, Buf^, BufTop, BufTop);
  290.     IoResult:= system.IoResult;
  291.   End;
  292.  
  293.  
  294. Begin
  295. End.
  296.  
  297. { -------------------------   DEMO ----------------- }
  298. Program TestFile;
  299.  
  300. Uses
  301.   FastFile;
  302.  
  303. Var
  304.   InFile,
  305.   OutFile : BufferedFile;
  306.   Data : Array[1..120] of byte;
  307.  
  308. Begin
  309.   New(InFile, Init($8000));            { Allocate a 32K buffer };
  310.   New(OutFile, Init($4000));           { 16K Buffer }
  311.   InFile^.Assign(Parameter(1));        { Assign input to a filename }
  312.   InFile^.Reset(sizeof(data));        
  313.   OutFile^.Assign(Parameter(2));
  314.   OutFile^.Rewrite(sizeof(data));
  315.   While not InFile^.EOF do begin 
  316.     InFile^.Read(Data);
  317.     if Data[1] <> 0 then OutFile^.Write(Data);
  318.   end;
  319.   InFile^.Close;
  320.   OutFile^.Close;
  321.   InFile^.Erase;
  322.   OutFile^.Rename(Parameter(1)); 
  323.   Dispose(InFile);                     { Close the file and free the memory }
  324.   Dispose(OutFile);
  325. End.
  326.  
  327.   As you see, this implements a very silly program which removes the original
  328. after stripping unwanted records from it.  Without the large RAM buffers, this
  329. would be an extremely slow, but since all READs and WRITEs and SEEKs and 
  330. everything else are done to RAM, few actual disk accesses result.  I used this
  331. in a USEnet mail processing program and the speed went from 15K/sec to
  332. 130K/sec.
  333.  
  334.   The easiest way to use it is to simply change structures like:
  335.  
  336. Assign(Filehandle, name);   --->   Filehandle^.Assign(name);
  337.  
  338.   ...in many cases a couple of Search..Replace passes are all that you need to
  339. modify your software to use this.  I've done it will all of my own and am very
  340. pleased.  
  341.  
  342.   Again, if you run into any problems, please let me know!  I can guarantee
  343. you only that it works fine for me.  :-)
  344.